[AGC002D]Stamp Rally

2020-02-13
Atcoder

题意

在无向图中,Q次询问从x,y出发到达恰好z个点经过的边编号的最大值的Min

题解

最大值最小,显然二分

分开二分太慢了,我们就一起二分

用堆会有两个log,过不去

可以在push的时候保证有序,同一深度的从左到右处理

调试记录

开始用堆T掉

ask里面可能有些询问先退出,因此不能用askl确定位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <cstdio>
#include <algorithm>
#include <queue>
const int maxn = 1e5 + 5;
const int INF = 0x3f3f3f3f;
using namespace std;
int n, m, Q, u[maxn], v[maxn];
int f[maxn], sz[maxn], x[maxn], y[maxn], z[maxn];
int getf(int x){
return f[x] == x ? x : f[x] = getf(f[x]);
}
int sum[maxn], ans[maxn];
struct A{
int l, r, askl, askr;
};
vector <A> vec[2];
vector <int> ask[2];
int calc(int id){
return sz[getf(x[id])] + (getf(x[id]) != getf(y[id])) * sz[getf(y[id])];
}
int main(){
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) scanf("%d%d", u + i, v + i);
scanf("%d", &Q);
for (int i = 1; i <= Q; i++){
scanf("%d%d%d", x + i, y + i, z + i);
ans[i] = INF; ask[0].push_back(i);
} vec[0].push_back(A{1, m, 0, Q});
int now, D = 0;
while (!vec[D].empty()){
for (int i = 1; i <= n; i++) f[i] = i, sz[i] = 1; now = 0;
for (int j = 0; j < vec[D].size(); j++){
A cur = vec[D][j]; int mid = cur.l + cur.r >> 1;
if (cur.l == cur.r){
for (int i = cur.askl; i < cur.askr; i++){
// if (mid == 5) printf("!%d\n", ask[D][i]);
ans[ask[D][i]] = min(ans[ask[D][i]], cur.l);
}
continue;
}
for (int i = now + 1; i <= mid; i++){
if (sz[u[i]] > sz[v[i]]) swap(u[i], v[i]);
if (getf(u[i]) != getf(v[i]))
sz[getf(v[i])] += sz[getf(u[i])],
f[getf(u[i])] = getf(v[i]);
}
now = mid;
int cnt[2]; cnt[0] = 0, cnt[1] = 0;
for (int i = cur.askl; i < cur.askr; i++)
if (calc(ask[D][i]) >= z[ask[D][i]]){
ask[D ^ 1].push_back(ask[D][i]), ++cnt[0];
// if (ask[D][i] == 5) puts("(1)");
}
if (cnt[0] > 0) vec[D ^ 1].push_back(A{cur.l, mid, ask[D ^ 1].size() - cnt[0], ask[D ^ 1].size()});
for (int i = cur.askl; i < cur.askr; i++)
if (calc(ask[D][i]) < z[ask[D][i]]){
ask[D ^ 1].push_back(ask[D][i]), ++cnt[1];
// if (ask[D][i] == 5) puts("(2)"), printf("(())%d\n", ask[D ^ 1].size());
}
if (cnt[1] > 0) vec[D ^ 1].push_back(A{mid + 1, cur.r, ask[D ^ 1].size() - cnt[1], ask[D ^ 1].size()});
}
vec[D].clear(); ask[D].clear(); D ^= 1;
}
for (int i = 1; i <= Q; i++) printf("%d\n", ans[i]);
return 0;
}